﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.Drawing;
using Rectangle = Microsoft.Xna.Framework.Rectangle;
using Color = Microsoft.Xna.Framework.Color;
using System.Xml.Serialization;
using System.Runtime.Serialization;

namespace QuestPrototype
{
    enum AnimationState 
    {
        play, loop, stop
    };
    /// <summary>
    /// This class handles the the logic requiered to draw and play animations from textures:
    ///     - updates the frame 
    ///     - draws the texture from the according to the current frame
    ///     - 3 modes: stop (stay on the first frame); play (stop when last frame is reached); loop (go back to first frame when last frame is reached)
    ///     - mode is set through the control functions
    ///     - frame interval (the amount of time each frame is shown before moving to next one) - not sure if there is a number that gives best results, 
    ///       seems to depend on specific animations.
    /// </summary>
    /// 

    [DataContract]
    public class Animation
    {
        [DataMember]
        private string Name;
        Texture2D AnimationStrip;
        private double FrameInterval;
        private double elapsed;
        private AnimationState state;
        private int FrameWidth;
        private int FrameHeight;
        private int NumberOfFrames;
        private int CurrentFrame;
        private Rectangle frame;
        private SpriteEffects flip;


        #region Animation constructors
        public Animation(string _Name, Texture2D _AnimationStrip, double _FrameInterval, int _FrameWidth, int _FrameHeight, int _NumberOfFrames)
        {
            this.Name = _Name;
            this.AnimationStrip = _AnimationStrip;
            this.FrameInterval = _FrameInterval;
            this.FrameWidth = _FrameWidth;
            this.FrameHeight = AnimationStrip.Height;
            this.NumberOfFrames = _NumberOfFrames;
            this.frame = new Rectangle(0, 0, _FrameWidth, _FrameHeight);
            this.CurrentFrame = 0;
            this.state = AnimationState.stop;
            this.flip = SpriteEffects.None;
        }
        public Animation(Animation anim)
            : this(anim.Name, anim.AnimationStrip, anim.FrameInterval, anim.FrameWidth, anim.FrameHeight, anim.NumberOfFrames)
        {
        }
        public Animation()
        {
        }
        #endregion

        public int GetWidth()
        {
            return FrameWidth;
        }
        public int GetHeight()
        {
            return FrameHeight;
        }

        #region Animation Update
        public void Update(GameTime gameTime)
        {
            //no need to play animation
            if (state == AnimationState.stop)
            {
                return;
            }
            //update time passed
            elapsed += gameTime.ElapsedGameTime.TotalSeconds;
            //frame interval is over, move to next frame
            while (elapsed > FrameInterval)
            {
                elapsed -= FrameInterval;
                //move frame forward

                CurrentFrame = ((CurrentFrame + 1) % NumberOfFrames);
                //got to end of animation
                if (CurrentFrame == 0 && state == AnimationState.play)
                {
                    state = AnimationState.stop;
                }
                //update frame rectangle to correct frame
                frame.X = CurrentFrame * FrameWidth;
            }

        }
        #endregion

        #region Animation Draw
        public void Draw(SpriteBatch spriteBatch, Rectangle location)
        {
            spriteBatch.Draw(AnimationStrip, location, frame, Color.White, 0f, Vector2.Zero, flip, 0f);
        }
        #endregion

        #region Animation controls
        public void play()
        {
            state = AnimationState.play;
        }
        public void stop()
        {
            state = AnimationState.stop;
        }
        public void loop()
        {
            state = AnimationState.loop;
        }
        public void flipNone()
        {
            flip = SpriteEffects.None;
        }
        public void flipHorizontal()
        {
            flip = SpriteEffects.FlipHorizontally;
        }
        public void flipVertical()
        {
            flip = SpriteEffects.FlipVertically;
        }
        #endregion
    }
}
